package com.black.knight.chess.model;

import java.util.ArrayList;

import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;

import com.black.knight.chess.R;
import com.black.knight.chess.SahMatActivity;
import com.black.knight.chess.components.ChessClock;
import com.black.knight.chess.domain.FEN;
import com.black.knight.chess.domain.Game;
import com.black.knight.chess.domain.Move;
import com.black.knight.chess.enums.ChessAction;
import com.black.knight.chess.enums.NewGame;
import com.facebook.android.Facebook;

public class SahModel {
	
	private static SahModel model;
	public static SahMatActivity context;

	private Integer[] fields;
	
	private ChessClock whiteClock = new ChessClock(context);
	private ChessClock blackClock = new ChessClock(context);
	
	private Game game;
	
	public static ChessAction lastAction;
	
	private String fenString;
	
	public static Integer screenWidth = 0;
	
	public static Integer screenHeight = 0;
	
	public Facebook facebook = new Facebook("113201652137799");
	
	public static Integer getTableWidth() { 
		if(screenWidth < screenHeight) {
			return screenWidth - (10 - SettingsModel.getInstance().getTableSize()) * 24; 
		} else {
			return screenHeight - (10 - SettingsModel.getInstance().getTableSize()) * 24;
		}
	}

	private Integer[] startPositions = {
            R.drawable.br, R.drawable.bn, R.drawable.bb, R.drawable.bq, R.drawable.bk, R.drawable.bb, R.drawable.bn, R.drawable.br,
            R.drawable.bp, R.drawable.bp, R.drawable.bp, R.drawable.bp, R.drawable.bp, R.drawable.bp, R.drawable.bp, R.drawable.bp,
            R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty,
            R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty,
            R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty,
            R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty, R.drawable.empty,
            R.drawable.wp, R.drawable.wp, R.drawable.wp, R.drawable.wp, R.drawable.wp, R.drawable.wp, R.drawable.wp, R.drawable.wp,
            R.drawable.wr, R.drawable.wn, R.drawable.wb, R.drawable.wq, R.drawable.wk, R.drawable.wb, R.drawable.wn, R.drawable.wr,
    };
	
	private int[] selectedFlags = new int[64];
	
	public SahModel() {
		reset(null);
	}
	
	public void reset(String fenString) {
		String token = SettingsModel.getInstance().getFacebookToken();
		Long expires = SettingsModel.getInstance().getFacebookTokenExpiration();
		
		if(token != null && token.length() > 0) {
            facebook.setAccessToken(token);
        }
        if(expires != 0) {
            facebook.setAccessExpires(expires);
        }
		
		this.game = new Game();
		
		if(fenString == null) {
			this.fields = startPositions.clone();
			this.fenString = null;
		} else {
			this.fenString = fenString;
			
			FEN fen = new FEN(fenString);
			
			this.fields = fen.getFields();
			if(fen.isWhitePlay()) {
				game.setCurrentPlayer(game.getPlayer1());
			} else {
				game.setCurrentPlayer(game.getPlayer2());
			}
		}
		
		this.selectedFlags = new int[64];
		this.whiteClock.reset();
		this.blackClock.reset();
		this.blackClock.stop();
		this.whiteClock.stop();
		this.whiteClock.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
		this.blackClock.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
		
		whiteClock.setPlayer(game.getPlayer1());
		blackClock.setPlayer(game.getPlayer2());
		
		PNGGamesModel.getInstance().setTags(null);
	}
	
	public void toggleClocks() {
		Game game = SahModel.getInstance().getGame();
		
		getWhiteClock().stop();
		getBlackClock().stop();
		
		if(game.getCurrentPlayer() != game.getPlayer1()) {
			getBlackClock().start();
		} else {	
			getWhiteClock().start();		
		}
	}
	
	public int getCount() {
		return fields.length;
	}
	
	public Integer getFigureCount(int figure) {
		Integer count = 0;
		for (int i = 0; i < fields.length; i++) {
			if(figure == fields[i]) count++;
		}
		
		return count;
	}
	
	public Integer getItem(int position) {
		return fields[position];
	}
	
	public void setItemId(int position, int item) {
		fields[position] = item;
	}
	
	public void moveFigure(int row, int column, int newRow, int newColumn) {
		setFigure(newRow, newColumn, getFigure(row, column));
		setFigure(row, column, R.drawable.empty);
	}
	
	public void moveFigure(Move move, int movePosition) {
		if(game.getMoves().size() > movePosition) {
			ArrayList<Move> tempList  = new ArrayList<Move>();
			for (int i = 0; i<movePosition; i++) {
				tempList.add(game.getMoves().get(i));
			}
			game.setMoves(tempList);
		}
		
		game.getMoves().add(move);
		
		if(!doRokada(move)) {
			setFigure(move.getNewRow(), move.getNewColumn(), move.getFigure());
			setFigure(move.getRow(), move.getColumn(), R.drawable.empty);
			
			if(move.isAnPasan()) {
				if(Move.isFigureWhite(move.getMovedFigure())) {
					move.setDestroyedFigure(R.drawable.bp);
				} else {
					move.setDestroyedFigure(R.drawable.wp);
				}
				
				setFigure(move.getRow(), move.getNewColumn(), R.drawable.empty);
			} else if(move.isPromote()) {
				setFigure(move.getNewRow(), move.getNewColumn(), move.getDerivedFigure());
				
				move.setDerivedFigure(move.getNewFigure());
			}
		}
	}
	
	public Move play(int position, boolean back) {
		Move move = game.getMoves().get(position);
		
		if(move.getResult().length() != 0) {
			if(back) {
				game.setSelectedIndex(game.getSelectedIndex() - 1);
				position--;
				
				move = game.getMoves().get(position);
			}
		}
		
		if(back) {
			SahModel.getInstance().getGame().togglePlayer();
			
			setFigure(move.getNewRow(), move.getNewColumn(), move.getDestroyedFigure());
			setFigure(move.getRow(), move.getColumn(), move.getMovedFigure());
			
			if(move.isCastle()) {
				if(Move.isFigureWhite(move.getMovedFigure())) {
					if(move.getNewColumn() == 6 && move.getNewRow() == 7) {
						setFigure(move.getNewRow(), 7, R.drawable.wr);
						setFigure(move.getNewRow(), 5, R.drawable.empty);
					} else if(move.getNewColumn() == 2 && move.getNewRow() == 7) {
						setFigure(move.getNewRow(), 0, R.drawable.wr);
						setFigure(move.getNewRow(), 3, R.drawable.empty);
					}
				} else if(Move.isFigureBlack(move.getMovedFigure())) {
					if(move.getNewColumn() == 6 && move.getNewRow() == 0) {
						setFigure(move.getNewRow(), 7, R.drawable.br);
						setFigure(move.getNewRow(), 5, R.drawable.empty);
					} else if(move.getNewColumn() == 2 && move.getNewRow() == 0) {
						setFigure(move.getNewRow(), 0, R.drawable.br);
						setFigure(move.getNewRow(), 3, R.drawable.empty);
					}					
				}
			} else if(move.isAnPasan()) {
				if(Move.isFigureWhite(move.getMovedFigure())) {
					setFigure(move.getRow(), move.getNewColumn(), R.drawable.bp);
				} else {
					setFigure(move.getRow(), move.getNewColumn(), R.drawable.wp);
				}
				setFigure(move.getNewRow(), move.getNewColumn(), R.drawable.empty);
			}
		} else {			
			move.preProcessPGN();
			
			SahModel.getInstance().getGame().togglePlayer();
			
			move.setDestroyedFigure(getFigure(move.getNewRow(), move.getNewColumn()));
			
			if(move.isCastle()) {
				if(doRokada(move)) {
					move.postProcessPGN();
					return move;
				}
			} if(move.isAnPasan()) {
				move.setDestroyedFigure(getFigure(move.getRow(), move.getNewColumn()));
				setFigure(move.getRow(), move.getNewColumn(), R.drawable.empty);
			} else if(move.isPromote()) {
				setFigure(move.getNewRow(), move.getNewColumn(), move.getDerivedFigure());
				setFigure(move.getRow(), move.getColumn(), R.drawable.empty);
				move.postProcessPGN();
				return move;
			}
			
			setFigure(move.getNewRow(), move.getNewColumn(), move.getMovedFigure());
			setFigure(move.getRow(), move.getColumn(), R.drawable.empty);
			
			move.postProcessPGN();
		}
		
		return move;
	}
	
	public boolean doRokada(Move move) {
		if(move.getFigure() == R.drawable.wk && move.getNewRow() == 7 && move.getNewColumn() == 6 && move.getColumn() == 4) {
			setFigure(move.getNewRow(), move.getNewColumn(), R.drawable.wk);
			setFigure(move.getRow(), move.getColumn(), R.drawable.empty);
			setFigure(7, 5, R.drawable.wr);
			setFigure(7, 7, R.drawable.empty);
		} else if(move.getFigure() == R.drawable.wk && move.getNewRow() == 7 && move.getNewColumn() == 2 && move.getColumn() == 4) {
			setFigure(move.getNewRow(), move.getNewColumn(), R.drawable.wk);
			setFigure(move.getRow(), move.getColumn(), R.drawable.empty);
			setFigure(7, 3, R.drawable.wr);
			setFigure(7, 0, R.drawable.empty);
		} else if(move.getFigure() == R.drawable.bk && move.getNewRow() == 0 && move.getNewColumn() == 6 && move.getColumn() == 4) {
			setFigure(move.getNewRow(), move.getNewColumn(), R.drawable.bk);
			setFigure(move.getRow(), move.getColumn(), R.drawable.empty);
			setFigure(0, 5, R.drawable.br);
			setFigure(0, 7, R.drawable.empty);
		} else if(move.getFigure() == R.drawable.bk && move.getNewRow() == 0 && move.getNewColumn() == 2 && move.getColumn() == 4) {
			setFigure(move.getNewRow(), move.getNewColumn(), R.drawable.bk);
			setFigure(move.getRow(), move.getColumn(), R.drawable.empty);
			setFigure(0, 3, R.drawable.br);
			setFigure(0, 0, R.drawable.empty);
		} else return false;
		
		return true;
	}
	
	public boolean isWhitePlay() {
		return game.isWhitePlay();
	}
	
	public void setFigure(int row, int column, int figure) {
		fields[row*8 + column] = figure;
	}
	
	public int getFigure(int row, int column) {
		return fields[row*8 + column];
	}
	
	public static SahModel getInstance() {
		if(model == null) {
			model = new SahModel();
		}
		
		return model;
	}

	public int[] getSelectedFlags() {
		return selectedFlags;
	}

	public void setSelectedFlags(int[] selectedFlags) {
		this.selectedFlags = selectedFlags;
	}
	
	public ChessClock getBlackClock() {
		return blackClock;
	}

	public ChessClock getWhiteClock() {
		return whiteClock;
	}

	public Game getGame() {
		return game;
	}

	public void setGame(Game game) {
		this.game = game;
	}
	
	public void setAutoRotate(boolean autoRotate) {
		SettingsModel.getInstance().setAutoRotate(autoRotate);
		
		if(!SahModel.getInstance().getGame().getCurrentPlayer().isWhitePlayer()) SahModel.context.rotate();
	}
	
	public boolean isAutoRotate() {
		return SettingsModel.getInstance().isAutoRotate() && NewGame.HUMAN.equals(SahModel.getInstance().getGame().getGameType());
	}

	public String getFenString() {
		return fenString;
	}

	public void setFenString(String fenString) {
		this.fenString = fenString;
	}
}
